package com.hjx.other;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 从数据库表中查询数据生成菜单树
 * 表结构
 * id
 * pid
 * menu_name
 *
 * 1  null root
 * 2  1    menu_1
 * 3  1    menu_2
 * 4  1    menu_3
 * 5  2    menu_1_1
 * 6  2    menu_1_2
 * 7  3    menu_2_1
 * 8  3    menu_2_2
 * 9  4    menu_3_1
 * 10 4    menu_3_2
 */
public class RecordToMenuTree {

    public static void main(String[] args) {
        List<MenuItem> menuItems = new ArrayList<MenuItem>(){{
            add(new MenuItem("1", "0", "root"));
            add(new MenuItem("2", "1", "menu_1"));
            add(new MenuItem("3", "1", "menu_2"));
            add(new MenuItem("4", "1", "menu_3"));
            add(new MenuItem("5", "2", "menu_1_1"));
            add(new MenuItem("6", "2", "menu_1_2"));
            add(new MenuItem("7", "3", "menu_2_1"));
            add(new MenuItem("8", "3", "menu_2_2"));
            add(new MenuItem("9", "4", "menu_3_1"));
            add(new MenuItem("10", "4", "menu_3_2"));
        }};

        tree(menuItems);
    }

    private static MenuTree tree(List<MenuItem> menuItems) {
        //1、按照pid分组
        Map<String, List<MenuItem>> groupingMappings = menuItems.stream().collect(Collectors.groupingBy(MenuItem::getPid));

        groupingMappings.forEach((k,v) -> {
            System.out.println(k + ":" + v);
        });

        //2、从根节点开始构造树结构
        List<MenuTree> menuTrees = constructMenuTree(groupingMappings, "0");
        System.out.println(menuTrees);
        return menuTrees.get(0);

    }

    /**
     * 循环加递归的方式构造子树， 递归退出的条件为 groupingMappings.get(pid) == null
     * @param groupingMappings
     * @param pid
     * @return
     */
    private static List<MenuTree> constructMenuTree(Map<String, List<MenuItem>> groupingMappings, String pid) {

        //1、初始化容器
        List<MenuTree> menuTrees = new ArrayList<>();

        //2、分组中能找到对应的pid且 i 小于该组元素个数 时继续循环
        for (int i = 0; groupingMappings.get(pid) != null && i < groupingMappings.get(pid).size(); i++) {
            MenuTree menuTree = new MenuTree();

            //设置PID
            menuTree.setPid(pid);

            //设置菜单名称
            MenuItem menuItem = groupingMappings.get(pid).get(i);
            String name = menuItem.getMenuName();
            menuTree.setName(name);

            //先构造下级菜单
            String id = menuItem.getId();
            List<MenuTree> menuTreeList = constructMenuTree(groupingMappings, id);

            //将构造好的下级菜单放到List中
            menuTree.setMenuTrees(menuTreeList);
            menuTrees.add(menuTree);
        }

        return menuTrees;
    }
}

class MenuTree {
    private String pid;
    private String name;
    private List<MenuTree> menuTrees;

    public MenuTree() {
    }

    public MenuTree(String id, String name, List<MenuTree> menuTrees) {
        this.pid = id;
        this.name = name;
        this.menuTrees = menuTrees;
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<MenuTree> getMenuTrees() {
        return menuTrees;
    }

    public void setMenuTrees(List<MenuTree> menuTrees) {
        this.menuTrees = menuTrees;
    }
}

class MenuItem {

    String id;
    String pid;
    String menuName;

    public MenuItem(String id, String pid, String menuName) {
        this.id = id;
        this.pid = pid;
        this.menuName = menuName;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getMenuName() {
        return menuName;
    }

    public void setMenuName(String menuName) {
        this.menuName = menuName;
    }

    @Override public String toString() {
        return "Menu{" +
            "id='" + id + '\'' +
            ", pid='" + pid + '\'' +
            ", menuName='" + menuName + '\'' +
            '}';
    }
}
